<!DOCTYPE html>
<html lang=zh>
<head>
    <meta charset="utf-8">
    
    <title>第三十章：SpringBoot使用MapStruct自动映射DTO | 恒宇少年De成长之路</title>
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
    <meta name="description" content="MapStruct是一种类型安全的bean映射类生成java注释处理器。我们要做的就是定义一个映射器接口，声明任何必需的映射方法。在编译的过程中，MapStruct会生成此接口的实现。该实现使用纯java方法调用的源和目标对象之间的映射，MapStruct节省了时间，通过生成代码完成繁琐和容易出错的代码逻辑。下面我们来揭开它的神秘面纱">
<meta name="keywords" content="SpringBoot">
<meta property="og:type" content="article">
<meta property="og:title" content="第三十章：SpringBoot使用MapStruct自动映射DTO">
<meta property="og:url" content="http://blog.yuqiyu.com/spring-boot-chapter-30/index.html">
<meta property="og:site_name" content="恒宇少年De成长之路">
<meta property="og:description" content="MapStruct是一种类型安全的bean映射类生成java注释处理器。我们要做的就是定义一个映射器接口，声明任何必需的映射方法。在编译的过程中，MapStruct会生成此接口的实现。该实现使用纯java方法调用的源和目标对象之间的映射，MapStruct节省了时间，通过生成代码完成繁琐和容易出错的代码逻辑。下面我们来揭开它的神秘面纱">
<meta property="og:locale" content="zh-CN">
<meta property="og:image" content="http://upload-images.jianshu.io/upload_images/4461954-f1d4cb64234b160a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240">
<meta property="og:updated_time" content="2018-02-21T06:39:57.968Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="第三十章：SpringBoot使用MapStruct自动映射DTO">
<meta name="twitter:description" content="MapStruct是一种类型安全的bean映射类生成java注释处理器。我们要做的就是定义一个映射器接口，声明任何必需的映射方法。在编译的过程中，MapStruct会生成此接口的实现。该实现使用纯java方法调用的源和目标对象之间的映射，MapStruct节省了时间，通过生成代码完成繁琐和容易出错的代码逻辑。下面我们来揭开它的神秘面纱">
<meta name="twitter:image" content="http://upload-images.jianshu.io/upload_images/4461954-f1d4cb64234b160a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240">
    

    
        <link rel="alternate" href="/" title="恒宇少年De成长之路" type="application/atom+xml" />
    

    

    <link rel="stylesheet" href="/libs/font-awesome/css/font-awesome.min.css">
    <link rel="stylesheet" href="/libs/open-sans/styles.css">
    <link rel="stylesheet" href="/libs/source-code-pro/styles.css">

    <link rel="stylesheet" href="/css/style.css">

    <script src="/libs/jquery/2.1.3/jquery.min.js"></script>
    
    
        <link rel="stylesheet" href="/libs/lightgallery/css/lightgallery.min.css">
    
    
        <link rel="stylesheet" href="/libs/justified-gallery/justifiedGallery.min.css">
    
    
    
    


</head>

<body>
    <div id="container">
        <header id="header">
    <div id="header-main" class="header-inner">
        <div class="outer">
            <a href="/" id="logo">
                <i class="logo"></i>
                <span class="site-title">恒宇少年De成长之路</span>
            </a>
            <nav id="main-nav">
                
                    <a class="main-nav-link" href="/.">首页</a>
                
                    <a class="main-nav-link" href="/archives">时间轴</a>
                
                    <a class="main-nav-link" href="/categories">文章专题</a>
                
                    <a class="main-nav-link" href="/tags">标签云</a>
                
                    <a class="main-nav-link" href="/about">关于我</a>
                
            </nav>
            
                
                <nav id="sub-nav">
                    <div class="profile" id="profile-nav">
                        <a id="profile-anchor" href="javascript:;">
                            <img class="avatar" src="/css/images/avatar.png" />
                            <i class="fa fa-caret-down"></i>
                        </a>
                    </div>
                </nav>
            
            <div id="search-form-wrap">

    <form class="search-form">
        <input type="text" class="ins-search-input search-form-input" placeholder="搜索" />
        <!--button type="submit" class="search-form-submit"></button-->
    </form>
    <div class="ins-search">
    <div class="ins-search-mask"></div>
    <div class="ins-search-container">
        <div class="ins-input-wrapper">
            <input type="text" class="ins-search-input" placeholder="想要查找什么..." />
            <span class="ins-close ins-selectable"><i class="fa fa-times-circle"></i></span>
        </div>
        <div class="ins-section-wrapper">
            <div class="ins-section-container"></div>
        </div>
    </div>
</div>
<script>
(function (window) {
    var INSIGHT_CONFIG = {
        TRANSLATION: {
            POSTS: '文章',
            PAGES: '页面',
            CATEGORIES: '分类',
            TAGS: '标签',
            UNTITLED: '(未命名)',
        },
        ROOT_URL: '/',
        CONTENT_URL: '/content.json',
    };
    window.INSIGHT_CONFIG = INSIGHT_CONFIG;
})(window);
</script>
<script src="/js/insight.js"></script>

</div>
        </div>
    </div>
    <div id="main-nav-mobile" class="header-sub header-inner">
        <table class="menu outer">
            <tr>
                
                    <td ><a  class="main-nav-link" href="/.">首页</a></td>
                
                    <td ><a  class="main-nav-link" href="/archives">时间轴</a></td>
                
                    <td ><a  class="main-nav-link" href="/categories">文章专题</a></td>
                
                    <td ><a  class="main-nav-link" href="/tags">标签云</a></td>
                
                    <td ><a  class="main-nav-link" href="/about">关于我</a></td>
                
                <td>
                    
    <div class="search-form">
        <input type="text" class="ins-search-input search-form-input" placeholder="搜索" />
    </div>

                </td>
            </tr>
        </table>
    </div>
</header>

        <div class="outer">
            
                

<aside id="profile">
    <div class="inner profile-inner">
        <div class="base-info profile-block">
            <img id="avatar" src="/css/images/avatar.png" />
            <h2 id="name">恒宇少年</h2>
            <h3 id="title">Java软件工程师 &amp; 程序猿</h3>
            <span id="location"><i class="fa fa-map-marker"></i>山东, 济南</span>
            <a id="follow" target="_blank" href="https://www.jianshu.com/u/092df3f77bca">关注我</a>
        </div>
        <div class="article-info profile-block">
            <div class="article-info-block">
                43
                <span>文章</span>
            </div>
            <div class="article-info-block">
                2
                <span>标签</span>
            </div>
        </div>
        
        <div class="profile-block social-links">
            <table>
                <tr>
                    
                    
                    <td>
                        <a href="http://github.com/ppoffice/hexo-theme-icarus" target="_blank" title="github" class=tooltip>
                            <i class="fa fa-github"></i>
                        </a>
                    </td>
                    
                    <td>
                        <a href="/" target="_blank" title="twitter" class=tooltip>
                            <i class="fa fa-twitter"></i>
                        </a>
                    </td>
                    
                    <td>
                        <a href="/" target="_blank" title="facebook" class=tooltip>
                            <i class="fa fa-facebook"></i>
                        </a>
                    </td>
                    
                    <td>
                        <a href="/" target="_blank" title="dribbble" class=tooltip>
                            <i class="fa fa-dribbble"></i>
                        </a>
                    </td>
                    
                    <td>
                        <a href="/" target="_blank" title="rss" class=tooltip>
                            <i class="fa fa-rss"></i>
                        </a>
                    </td>
                    
                </tr>
            </table>
        </div>
        
    </div>
</aside>

            
            <section id="main"><article id="post-spring-boot-chapter-30" class="article article-type-post" itemscope itemprop="blogPost">
    <div class="article-inner">
        
        
            <header class="article-header">
                
    
        <h1 class="article-title" itemprop="name">
            第三十章：SpringBoot使用MapStruct自动映射DTO
        </h1>
    

                
                    <div class="article-meta">
                        
    <div class="article-date">
        <i class="fa fa-calendar"></i>
        <a href="/spring-boot-chapter-30/">
            <time datetime="2017-08-19T16:00:00.000Z" itemprop="datePublished">2017-08-20</time>
        </a>
    </div>


                        
    <div class="article-category">
    	<i class="fa fa-folder"></i>
        <a class="article-category-link" href="/categories/SpringBoot-核心技术/">SpringBoot 核心技术</a>
    </div>

                        
    <div class="article-tag">
        <i class="fa fa-tag"></i>
        <a class="tag-link" href="/tags/SpringBoot/">SpringBoot</a>
    </div>

                    </div>
                
            </header>
        
        
        <div class="article-entry" itemprop="articleBody">
        
            
            <p><code>MapStruct</code>是一种类型安全的<code>bean映射</code>类生成java注释处理器。<br>我们要做的就是定义一个映射器接口，声明任何必需的映射方法。在编译的过程中，<code>MapStruct</code>会生成此接口的实现。该实现使用纯java方法调用的源和目标对象之间的映射，<code>MapStruct</code>节省了时间，通过生成代码完成繁琐和容易出错的代码逻辑。下面我们来揭开它的神秘面纱<br><a id="more"></a></p>
<h1 id="本章目标"><a href="#本章目标" class="headerlink" title="本章目标"></a>本章目标</h1><p>基于<code>SpringBoot</code>平台完成<code>MapStruct</code>映射框架的集成。</p>
<h1 id="SpringBoot-企业级核心技术学习专题"><a href="#SpringBoot-企业级核心技术学习专题" class="headerlink" title="SpringBoot 企业级核心技术学习专题"></a>SpringBoot 企业级核心技术学习专题</h1><table>
<thead>
<tr>
<th style="text-align:center">专题</th>
<th style="text-align:left">专题名称</th>
<th style="text-align:left">专题描述</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">001</td>
<td style="text-align:left"><a href="http://www.jianshu.com/c/3f69deddbed3" target="_blank" rel="noopener">Spring Boot 核心技术</a></td>
<td style="text-align:left">讲解SpringBoot一些企业级层面的核心组件</td>
</tr>
<tr>
<td style="text-align:center">002</td>
<td style="text-align:left"><a href="https://gitee.com/hengboy/spring-boot-chapter" target="_blank" rel="noopener">Spring Boot 核心技术章节源码</a></td>
<td style="text-align:left">Spring Boot 核心技术简书每一篇文章码云对应源码</td>
</tr>
<tr>
<td style="text-align:center">003</td>
<td style="text-align:left"><a href="http://www.jianshu.com/c/1faac22666e7" target="_blank" rel="noopener">Spring Cloud 核心技术</a></td>
<td style="text-align:left">对Spring Cloud核心技术全面讲解</td>
</tr>
<tr>
<td style="text-align:center">004</td>
<td style="text-align:left"><a href="https://gitee.com/hengboy/spring-cloud-chapter" target="_blank" rel="noopener">Spring Cloud 核心技术章节源码</a></td>
<td style="text-align:left">Spring Cloud 核心技术简书每一篇文章对应源码</td>
</tr>
<tr>
<td style="text-align:center">005</td>
<td style="text-align:left"><a href="http://www.jianshu.com/c/ab4789177827" target="_blank" rel="noopener">QueryDSL 核心技术</a></td>
<td style="text-align:left">全面讲解QueryDSL核心技术以及基于SpringBoot整合SpringDataJPA</td>
</tr>
<tr>
<td style="text-align:center">006</td>
<td style="text-align:left"><a href="http://www.jianshu.com/c/f1b269bb2fd6" target="_blank" rel="noopener">SpringDataJPA 核心技术</a></td>
<td style="text-align:left">全面讲解SpringDataJPA核心技术</td>
</tr>
</tbody>
</table>
<h1 id="构建项目"><a href="#构建项目" class="headerlink" title="构建项目"></a>构建项目</h1><p>我们使用idea开发工具创建一个<code>SpringBoot</code>项目，添加相应的依赖，pom.xml配置文件如下所示：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br></pre></td><td class="code"><pre><span class="line">...省略部分代码</span><br><span class="line">&lt;parent&gt;</span><br><span class="line">		&lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;</span><br><span class="line">		&lt;artifactId&gt;spring-boot-starter-parent&lt;/artifactId&gt;</span><br><span class="line">		&lt;version&gt;1.5.6.RELEASE&lt;/version&gt;</span><br><span class="line">		&lt;relativePath/&gt; &lt;!-- lookup parent from repository --&gt;</span><br><span class="line">	&lt;/parent&gt;</span><br><span class="line"></span><br><span class="line">	&lt;properties&gt;</span><br><span class="line">		&lt;project.build.sourceEncoding&gt;UTF-8&lt;/project.build.sourceEncoding&gt;</span><br><span class="line">		&lt;project.reporting.outputEncoding&gt;UTF-8&lt;/project.reporting.outputEncoding&gt;</span><br><span class="line">		&lt;java.version&gt;1.8&lt;/java.version&gt;</span><br><span class="line">		&lt;org.mapstruct.version&gt;1.2.0.CR1&lt;/org.mapstruct.version&gt;</span><br><span class="line">	&lt;/properties&gt;</span><br><span class="line"></span><br><span class="line">	&lt;dependencies&gt;</span><br><span class="line">		&lt;dependency&gt;</span><br><span class="line">			&lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;</span><br><span class="line">			&lt;artifactId&gt;spring-boot-starter-data-jpa&lt;/artifactId&gt;</span><br><span class="line">		&lt;/dependency&gt;</span><br><span class="line">		&lt;dependency&gt;</span><br><span class="line">			&lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;</span><br><span class="line">			&lt;artifactId&gt;spring-boot-starter-web&lt;/artifactId&gt;</span><br><span class="line">		&lt;/dependency&gt;</span><br><span class="line"></span><br><span class="line">		&lt;dependency&gt;</span><br><span class="line">			&lt;groupId&gt;mysql&lt;/groupId&gt;</span><br><span class="line">			&lt;artifactId&gt;mysql-connector-java&lt;/artifactId&gt;</span><br><span class="line">			&lt;scope&gt;runtime&lt;/scope&gt;</span><br><span class="line">		&lt;/dependency&gt;</span><br><span class="line">		&lt;dependency&gt;</span><br><span class="line">			&lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;</span><br><span class="line">			&lt;artifactId&gt;spring-boot-starter-tomcat&lt;/artifactId&gt;</span><br><span class="line">			&lt;!--&lt;scope&gt;provided&lt;/scope&gt;--&gt;</span><br><span class="line">		&lt;/dependency&gt;</span><br><span class="line">		&lt;dependency&gt;</span><br><span class="line">			&lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;</span><br><span class="line">			&lt;artifactId&gt;spring-boot-starter-test&lt;/artifactId&gt;</span><br><span class="line">			&lt;scope&gt;test&lt;/scope&gt;</span><br><span class="line">		&lt;/dependency&gt;</span><br><span class="line"></span><br><span class="line">		&lt;!--mapStruct依赖--&gt;</span><br><span class="line">		&lt;dependency&gt;</span><br><span class="line">			&lt;groupId&gt;org.mapstruct&lt;/groupId&gt;</span><br><span class="line">			&lt;artifactId&gt;mapstruct-jdk8&lt;/artifactId&gt;</span><br><span class="line">			&lt;version&gt;$&#123;org.mapstruct.version&#125;&lt;/version&gt;</span><br><span class="line">		&lt;/dependency&gt;</span><br><span class="line">		&lt;dependency&gt;</span><br><span class="line">			&lt;groupId&gt;org.mapstruct&lt;/groupId&gt;</span><br><span class="line">			&lt;artifactId&gt;mapstruct-processor&lt;/artifactId&gt;</span><br><span class="line">			&lt;version&gt;$&#123;org.mapstruct.version&#125;&lt;/version&gt;</span><br><span class="line">			&lt;scope&gt;provided&lt;/scope&gt;</span><br><span class="line">		&lt;/dependency&gt;</span><br><span class="line">		&lt;dependency&gt;</span><br><span class="line">			&lt;groupId&gt;javax.inject&lt;/groupId&gt;</span><br><span class="line">			&lt;artifactId&gt;javax.inject&lt;/artifactId&gt;</span><br><span class="line">			&lt;version&gt;1&lt;/version&gt;</span><br><span class="line">		&lt;/dependency&gt;</span><br><span class="line">		</span><br><span class="line">		&lt;dependency&gt;</span><br><span class="line">			&lt;groupId&gt;com.alibaba&lt;/groupId&gt;</span><br><span class="line">			&lt;artifactId&gt;druid&lt;/artifactId&gt;</span><br><span class="line">			&lt;version&gt;1.0.31&lt;/version&gt;</span><br><span class="line">		&lt;/dependency&gt;</span><br><span class="line">		&lt;dependency&gt;</span><br><span class="line">			&lt;groupId&gt;org.projectlombok&lt;/groupId&gt;</span><br><span class="line">			&lt;artifactId&gt;lombok&lt;/artifactId&gt;</span><br><span class="line">		&lt;/dependency&gt;</span><br><span class="line">	&lt;/dependencies&gt;</span><br><span class="line">....省略部分代码</span><br></pre></td></tr></table></figure></p>
<p>集成MapStruct官方提供了两种方式，上面配置文件内我们采用的是直接添加Maven依赖，而官方文档还提供了另外一种方式，采用Maven插件形式配置，配置如下所示：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line">...引用官方文档</span><br><span class="line">...</span><br><span class="line">&lt;properties&gt;</span><br><span class="line">    &lt;org.mapstruct.version&gt;1.2.0.CR1&lt;/org.mapstruct.version&gt;</span><br><span class="line">&lt;/properties&gt;</span><br><span class="line">...</span><br><span class="line">&lt;dependencies&gt;</span><br><span class="line">    &lt;dependency&gt;</span><br><span class="line">        &lt;groupId&gt;org.mapstruct&lt;/groupId&gt;</span><br><span class="line">        &lt;artifactId&gt;mapstruct-jdk8&lt;/artifactId&gt;</span><br><span class="line">        &lt;version&gt;$&#123;org.mapstruct.version&#125;&lt;/version&gt;</span><br><span class="line">    &lt;/dependency&gt;</span><br><span class="line">&lt;/dependencies&gt;</span><br><span class="line">...</span><br><span class="line">&lt;build&gt;</span><br><span class="line">    &lt;plugins&gt;</span><br><span class="line">        &lt;plugin&gt;</span><br><span class="line">            &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;</span><br><span class="line">            &lt;artifactId&gt;maven-compiler-plugin&lt;/artifactId&gt;</span><br><span class="line">            &lt;version&gt;3.5.1&lt;/version&gt;</span><br><span class="line">            &lt;configuration&gt;</span><br><span class="line">                &lt;source&gt;1.8&lt;/source&gt;</span><br><span class="line">                &lt;target&gt;1.8&lt;/target&gt;</span><br><span class="line">                &lt;annotationProcessorPaths&gt;</span><br><span class="line">                    &lt;path&gt;</span><br><span class="line">                        &lt;groupId&gt;org.mapstruct&lt;/groupId&gt;</span><br><span class="line">                        &lt;artifactId&gt;mapstruct-processor&lt;/artifactId&gt;</span><br><span class="line">                        &lt;version&gt;$&#123;org.mapstruct.version&#125;&lt;/version&gt;</span><br><span class="line">                    &lt;/path&gt;</span><br><span class="line">                &lt;/annotationProcessorPaths&gt;</span><br><span class="line">            &lt;/configuration&gt;</span><br><span class="line">        &lt;/plugin&gt;</span><br><span class="line">    &lt;/plugins&gt;</span><br><span class="line">&lt;/build&gt;</span><br><span class="line">...</span><br></pre></td></tr></table></figure></p>
<p>我个人比较喜欢采用第一种方式，不需要配置过多的插件，依赖方式比较方便。<br>接下来我们开始配置下数据库连接信息以及简单的两张表的SpringDataJPA相关接口。</p>
<h2 id="数据库连接信息"><a href="#数据库连接信息" class="headerlink" title="数据库连接信息"></a>数据库连接信息</h2><p>在resource下新创建一个application.yml文件，并添加如下数据库连接配置：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line">spring:</span><br><span class="line">  datasource:</span><br><span class="line">    type: com.alibaba.druid.pool.DruidDataSource</span><br><span class="line">    driver-class-name: com.mysql.jdbc.Driver</span><br><span class="line">    url: jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8</span><br><span class="line">    username: root</span><br><span class="line">    password: 123456</span><br><span class="line">    #最大活跃数</span><br><span class="line">    maxActive: 20</span><br><span class="line">    #初始化数量</span><br><span class="line">    initialSize: 1</span><br><span class="line">    #最大连接等待超时时间</span><br><span class="line">    maxWait: 60000</span><br><span class="line">    #打开PSCache，并且指定每个连接PSCache的大小</span><br><span class="line">    poolPreparedStatements: true</span><br><span class="line">    maxPoolPreparedStatementPerConnectionSize: 20</span><br><span class="line">    #通过connectionProperties属性来打开mergeSql功能；慢SQL记录</span><br><span class="line">    #connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000</span><br><span class="line">    minIdle: 1</span><br><span class="line">    timeBetweenEvictionRunsMillis: 60000</span><br><span class="line">    minEvictableIdleTimeMillis: 300000</span><br><span class="line">    validationQuery: select 1 from dual</span><br><span class="line">    testWhileIdle: true</span><br><span class="line">    testOnBorrow: false</span><br><span class="line">    testOnReturn: false</span><br><span class="line">    #配置监控统计拦截的filters，去掉后监控界面sql将无法统计,&apos;wall&apos;用于防火墙</span><br><span class="line">    filters: stat, wall, log4j</span><br><span class="line">  jpa:</span><br><span class="line">    properties:</span><br><span class="line">      hibernate:</span><br><span class="line">        show_sql: true</span><br><span class="line">        format_sql: true</span><br></pre></td></tr></table></figure></p>
<p>有关SpringDataJPA相关的学习请访问<a href="http://www.jianshu.com/p/b6932740f3c0" target="_blank" rel="noopener">第三章：SpringBoot使用SpringDataJPA完成CRUD</a>，我们在数据库内创建两张表信息分别是商品基本信息表、商品类型表。<br>两张表有相应的关联，我们在不采用连接查询的方式模拟使用<code>MapStruct</code>，表信息如下所示：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">--商品类型信息表</span><br><span class="line">CREATE TABLE `good_types` (</span><br><span class="line">  `tgt_id` int(11) NOT NULL AUTO_INCREMENT,</span><br><span class="line">  `tgt_name` varchar(30) DEFAULT NULL,</span><br><span class="line">  `tgt_is_show` int(1) DEFAULT NULL,</span><br><span class="line">  `tgt_order` int(255) DEFAULT NULL,</span><br><span class="line">  PRIMARY KEY (`tgt_id`)</span><br><span class="line">) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;</span><br><span class="line"></span><br><span class="line">--商品基本信息表</span><br><span class="line">CREATE TABLE `good_infos` (</span><br><span class="line">  `tg_id` int(11) NOT NULL AUTO_INCREMENT,</span><br><span class="line">  `tg_type_id` int(11) DEFAULT NULL,</span><br><span class="line">  `tg_title` varchar(30) DEFAULT NULL,</span><br><span class="line">  `tg_price` decimal(8,2) DEFAULT NULL,</span><br><span class="line">  `tg_order` int(2) DEFAULT NULL,</span><br><span class="line">  PRIMARY KEY (`tg_id`)</span><br><span class="line">) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;</span><br><span class="line"></span><br><span class="line">INSERT INTO `good_types` VALUES (&apos;1&apos;, &apos;青菜&apos;, &apos;1&apos;, &apos;1&apos;);</span><br><span class="line">INSERT INTO `good_infos` VALUES (&apos;1&apos;, &apos;1&apos;, &apos;芹菜&apos;, &apos;12.40&apos;, &apos;1&apos;);</span><br></pre></td></tr></table></figure></p>
<p>下面我们根据这两张表创建对应的实体类。</p>
<h4 id="商品类型实体"><a href="#商品类型实体" class="headerlink" title="商品类型实体"></a>商品类型实体</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line">package com.yuqiyu.chapter30.bean;</span><br><span class="line"></span><br><span class="line">import lombok.Data;</span><br><span class="line"></span><br><span class="line">import javax.persistence.Column;</span><br><span class="line">import javax.persistence.Entity;</span><br><span class="line">import javax.persistence.Id;</span><br><span class="line">import javax.persistence.Table;</span><br><span class="line"></span><br><span class="line">/**</span><br><span class="line"> * ========================</span><br><span class="line"> * Created with IntelliJ IDEA.</span><br><span class="line"> * User：恒宇少年</span><br><span class="line"> * Date：2017/8/20</span><br><span class="line"> * Time：11:17</span><br><span class="line"> * 码云：http://git.oschina.net/jnyqy</span><br><span class="line"> * ========================</span><br><span class="line"> */</span><br><span class="line">@Entity</span><br><span class="line">@Table(name = &quot;good_types&quot;)</span><br><span class="line">@Data</span><br><span class="line">public class GoodTypeBean</span><br><span class="line">&#123;</span><br><span class="line">    @Id</span><br><span class="line">    @Column(name = &quot;tgt_id&quot;)</span><br><span class="line">    private Long id;</span><br><span class="line"></span><br><span class="line">    @Column(name = &quot;tgt_name&quot;)</span><br><span class="line">    private String name;</span><br><span class="line">    @Column(name = &quot;tgt_is_show&quot;)</span><br><span class="line">    private int show;</span><br><span class="line">    @Column(name = &quot;tgt_order&quot;)</span><br><span class="line">    private int order;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h4 id="商品基本信息实体"><a href="#商品基本信息实体" class="headerlink" title="商品基本信息实体"></a>商品基本信息实体</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line">package com.yuqiyu.chapter30.bean;</span><br><span class="line"></span><br><span class="line">import lombok.Data;</span><br><span class="line"></span><br><span class="line">import javax.persistence.Column;</span><br><span class="line">import javax.persistence.Entity;</span><br><span class="line">import javax.persistence.Id;</span><br><span class="line">import javax.persistence.Table;</span><br><span class="line"></span><br><span class="line">/**</span><br><span class="line"> * ========================</span><br><span class="line"> * Created with IntelliJ IDEA.</span><br><span class="line"> * User：恒宇少年</span><br><span class="line"> * Date：2017/8/20</span><br><span class="line"> * Time：11:16</span><br><span class="line"> * 码云：http://git.oschina.net/jnyqy</span><br><span class="line"> * ========================</span><br><span class="line"> */</span><br><span class="line">@Entity</span><br><span class="line">@Table(name = &quot;good_infos&quot;)</span><br><span class="line">@Data</span><br><span class="line">public class GoodInfoBean</span><br><span class="line">&#123;</span><br><span class="line">    @Id</span><br><span class="line">    @Column(name = &quot;tg_id&quot;)</span><br><span class="line">    private Long id;</span><br><span class="line">    @Column(name = &quot;tg_title&quot;)</span><br><span class="line">    private String title;</span><br><span class="line">    @Column(name = &quot;tg_price&quot;)</span><br><span class="line">    private double price;</span><br><span class="line">    @Column(name = &quot;tg_order&quot;)</span><br><span class="line">    private int order;</span><br><span class="line">    @Column(name = &quot;tg_type_id&quot;)</span><br><span class="line">    private Long typeId;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>接下来我们继续创建相关的JPA。</p>
<h4 id="商品类型JPA"><a href="#商品类型JPA" class="headerlink" title="商品类型JPA"></a>商品类型JPA</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">package com.yuqiyu.chapter30.jpa;</span><br><span class="line"></span><br><span class="line">import com.yuqiyu.chapter30.bean.GoodTypeBean;</span><br><span class="line">import org.springframework.data.jpa.repository.JpaRepository;</span><br><span class="line"></span><br><span class="line">/**</span><br><span class="line"> * ========================</span><br><span class="line"> * Created with IntelliJ IDEA.</span><br><span class="line"> * User：恒宇少年</span><br><span class="line"> * Date：2017/8/20</span><br><span class="line"> * Time：11:24</span><br><span class="line"> * 码云：http://git.oschina.net/jnyqy</span><br><span class="line"> * ========================</span><br><span class="line"> */</span><br><span class="line">public interface GoodTypeJPA</span><br><span class="line">    extends JpaRepository&lt;GoodTypeBean,Long&gt;</span><br><span class="line">&#123;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h4 id="商品信息JPA"><a href="#商品信息JPA" class="headerlink" title="商品信息JPA"></a>商品信息JPA</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">package com.yuqiyu.chapter30.jpa;</span><br><span class="line"></span><br><span class="line">import com.yuqiyu.chapter30.bean.GoodInfoBean;</span><br><span class="line">import org.springframework.data.jpa.repository.JpaRepository;</span><br><span class="line"></span><br><span class="line">/**</span><br><span class="line"> * ========================</span><br><span class="line"> * Created with IntelliJ IDEA.</span><br><span class="line"> * User：恒宇少年</span><br><span class="line"> * Date：2017/8/20</span><br><span class="line"> * Time：11:23</span><br><span class="line"> * 码云：http://git.oschina.net/jnyqy</span><br><span class="line"> * ========================</span><br><span class="line"> */</span><br><span class="line">public interface GoodInfoJPA</span><br><span class="line">    extends JpaRepository&lt;GoodInfoBean,Long&gt;</span><br><span class="line">&#123;</span><br><span class="line">    </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h1 id="配置MapStruct"><a href="#配置MapStruct" class="headerlink" title="配置MapStruct"></a>配置MapStruct</h1><p>到目前为止我们的准备工作差不多完成了，下面我们开始配置使用<code>MapStruct</code>。我们的最终目的是为了返回一个自定义的DTO实体，那么我们就先来创建这个DTO，DTO的代码如下所示：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line">package com.yuqiyu.chapter30.dto;</span><br><span class="line"></span><br><span class="line">import lombok.Data;</span><br><span class="line"></span><br><span class="line">/**</span><br><span class="line"> * 转换Dto</span><br><span class="line"> * ========================</span><br><span class="line"> * Created with IntelliJ IDEA.</span><br><span class="line"> * User：恒宇少年</span><br><span class="line"> * Date：2017/8/20</span><br><span class="line"> * Time：11:25</span><br><span class="line"> * 码云：http://git.oschina.net/jnyqy</span><br><span class="line"> * ========================</span><br><span class="line"> */</span><br><span class="line">@Data</span><br><span class="line">public class GoodInfoDTO</span><br><span class="line">&#123;</span><br><span class="line">    //商品编号</span><br><span class="line">    private String goodId;</span><br><span class="line">    //商品名称</span><br><span class="line">    private String goodName;</span><br><span class="line">    //商品价格</span><br><span class="line">    private double goodPrice;</span><br><span class="line">    //类型名称</span><br><span class="line">    private String typeName;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>可以看到GoodInfoDTO实体内集成了商品信息、商品类型两张表内的数据，对应查询出信息后，我们需要使用<code>MapStruct</code>自动映射到GoodInfoDTO。</p>
<h3 id="创建Mapper"><a href="#创建Mapper" class="headerlink" title="创建Mapper"></a>创建Mapper</h3><p><code>Mapper</code>这个定义一般是被广泛应用到<code>MyBatis</code>半自动化ORM框架上，而这里的Mapper跟<code>Mybatis</code>没有关系。下面我们先来看下代码，如下所示：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line">package com.yuqiyu.chapter30.mapper;</span><br><span class="line"></span><br><span class="line">import com.yuqiyu.chapter30.bean.GoodInfoBean;</span><br><span class="line">import com.yuqiyu.chapter30.bean.GoodTypeBean;</span><br><span class="line">import com.yuqiyu.chapter30.dto.GoodInfoDTO;</span><br><span class="line">import org.mapstruct.Mapper;</span><br><span class="line">import org.mapstruct.Mapping;</span><br><span class="line">import org.mapstruct.Mappings;</span><br><span class="line"></span><br><span class="line">/**</span><br><span class="line"> * 配置映射</span><br><span class="line"> * ========================</span><br><span class="line"> * Created with IntelliJ IDEA.</span><br><span class="line"> * User：恒宇少年</span><br><span class="line"> * Date：2017/8/20</span><br><span class="line"> * Time：11:26</span><br><span class="line"> * 码云：http://git.oschina.net/jnyqy</span><br><span class="line"> * ========================</span><br><span class="line"> */</span><br><span class="line">@Mapper(componentModel = &quot;spring&quot;)</span><br><span class="line">//@Mapper</span><br><span class="line">public interface GoodInfoMapper</span><br><span class="line">&#123;</span><br><span class="line">    //public static GoodInfoMapper MAPPER = Mappers.getMapper(GoodInfoMapper.class);</span><br><span class="line"></span><br><span class="line">    @Mappings(&#123;</span><br><span class="line">            @Mapping(source = &quot;type.name&quot;,target = &quot;typeName&quot;),</span><br><span class="line">            @Mapping(source = &quot;good.id&quot;,target = &quot;goodId&quot;),</span><br><span class="line">            @Mapping(source = &quot;good.title&quot;,target = &quot;goodName&quot;),</span><br><span class="line">            @Mapping(source = &quot;good.price&quot;,target = &quot;goodPrice&quot;)</span><br><span class="line">    &#125;)</span><br><span class="line">    public GoodInfoDTO from(GoodInfoBean good, GoodTypeBean type);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>可以看到GoodInfoMapper是一个接口的形式存在的，当然也可以是一个抽象类，如果你需要在转换的时候才用个性化的定制的时候可以采用抽象类的方式，相应的代码配置官方文档已经声明。<br><code>@Mapper</code>注解是用于标注接口、抽象类是被<code>MapStruct</code>自动映射的标识，只有存在该注解才会将内部的接口方法自动实现。<br><code>MapStruct</code>为我们提供了多种的获取Mapper的方式，比较常用的两种分别是</p>
<h5 id="默认配置"><a href="#默认配置" class="headerlink" title="默认配置"></a>默认配置</h5><p>默认配置，我们不需要做过多的配置内容，获取Mapper的方式就是采用<code>Mappers</code>通过动态工厂内部反射机制完成Mapper实现类的获取。<br>默认方式获取Mapper如下所示：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">//Mapper接口内部定义</span><br><span class="line">public static GoodInfoMapper MAPPER = Mappers.getMapper(GoodInfoMapper.class);</span><br><span class="line"></span><br><span class="line">//外部调用</span><br><span class="line">GoodInfoMapper.MAPPER.from(goodBean,goodTypeBean);</span><br></pre></td></tr></table></figure></p>
<h5 id="Spring方式配置"><a href="#Spring方式配置" class="headerlink" title="Spring方式配置"></a>Spring方式配置</h5><p><code>Spring</code>方式我们需要在<code>@Mapper</code>注解内添加<code>componentModel</code>属性值，配置后在外部可以采用<code>@Autowired</code>方式注入Mapper实现类完成映射方法调用。<br>Spring方式获取Mapper如下所示：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">//注解配置</span><br><span class="line">@Mapper(componentModel = &quot;spring&quot;)</span><br><span class="line"></span><br><span class="line">//注入Mapper实现类</span><br><span class="line">@Autowired</span><br><span class="line">private GoodInfoMapper goodInfoMapper;</span><br><span class="line"></span><br><span class="line">//调用</span><br><span class="line">goodInfoMapper.from(goodBean,goodTypeBean);</span><br></pre></td></tr></table></figure></p>
<h5 id="Mappings-amp-Mapping"><a href="#Mappings-amp-Mapping" class="headerlink" title="@Mappings &amp; @Mapping"></a>@Mappings &amp; @Mapping</h5><p>在<code>Mapper</code>接口定义方法上面声明了一系列的注解映射<code>@Mapping</code>以及<code>@Mappings</code>，那么这两个注解是用来干什么工作的呢？<br><code>@Mapping</code>注解我们用到了两个属性，分别是<code>source</code>、<code>target</code></p>
<p><code>source</code>代表的是映射接口方法内的参数名称，如果是基本类型的参数，参数名可以直接作为<code>source</code>的内容，如果是实体类型，则可以采用实体参数名.字段名的方式作为<code>source</code>的内容，配置如上面<code>GoodInfoMapper</code>内容所示。</p>
<p><code>target</code>代表的是映射到方法方法值内的字段名称，配置如上面<code>GoodInfoMapper</code>所示。</p>
<h4 id="查看Mapper实现"><a href="#查看Mapper实现" class="headerlink" title="查看Mapper实现"></a>查看Mapper实现</h4><p>下面我们执行maven compile命令，到target/generated-sources/annotations目录下查看对应<code>Mapper</code>实现类，实现类代码如下所示：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line">package com.yuqiyu.chapter30.mapper;</span><br><span class="line"></span><br><span class="line">import com.yuqiyu.chapter30.bean.GoodInfoBean;</span><br><span class="line">import com.yuqiyu.chapter30.bean.GoodTypeBean;</span><br><span class="line">import com.yuqiyu.chapter30.dto.GoodInfoDTO;</span><br><span class="line">import javax.annotation.Generated;</span><br><span class="line">import org.springframework.stereotype.Component;</span><br><span class="line"></span><br><span class="line">@Generated(</span><br><span class="line">    value = &quot;org.mapstruct.ap.MappingProcessor&quot;,</span><br><span class="line">    date = &quot;2017-08-20T12:52:52+0800&quot;,</span><br><span class="line">    comments = &quot;version: 1.2.0.CR1, compiler: javac, environment: Java 1.8.0_111 (Oracle Corporation)&quot;</span><br><span class="line">)</span><br><span class="line">@Component</span><br><span class="line">public class GoodInfoMapperImpl implements GoodInfoMapper &#123;</span><br><span class="line"></span><br><span class="line">    @Override</span><br><span class="line">    public GoodInfoDTO from(GoodInfoBean good, GoodTypeBean type) &#123;</span><br><span class="line">        if ( good == null &amp;&amp; type == null ) &#123;</span><br><span class="line">            return null;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        GoodInfoDTO goodInfoDTO = new GoodInfoDTO();</span><br><span class="line"></span><br><span class="line">        if ( good != null ) &#123;</span><br><span class="line">            if ( good.getId() != null ) &#123;</span><br><span class="line">                goodInfoDTO.setGoodId( String.valueOf( good.getId() ) );</span><br><span class="line">            &#125;</span><br><span class="line">            goodInfoDTO.setGoodName( good.getTitle() );</span><br><span class="line">            goodInfoDTO.setGoodPrice( good.getPrice() );</span><br><span class="line">        &#125;</span><br><span class="line">        if ( type != null ) &#123;</span><br><span class="line">            goodInfoDTO.setTypeName( type.getName() );</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        return goodInfoDTO;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p><code>MapStruct</code>根据我们配置的<code>@Mapping</code>注解自动将<code>source</code>实体内的字段进行了调用<code>target</code>实体内字段的setXxx方法赋值，并且做出了一切参数验证。<br>我们采用了<code>Spring方式</code>获取<code>Mapper</code>，在自动生成的实现类上<code>MapStruct</code>为我们自动添加了<code>@Component</code>Spring声明式注入注解配置。</p>
<h1 id="运行测试"><a href="#运行测试" class="headerlink" title="运行测试"></a>运行测试</h1><p>下面我们来创建一个测试的Controller，用于访问具体请求地址时查询出商品的基本信息以及商品的类型后调用<code>GoodInfoMapper.from(xxx,xxx)</code>方法完成返回<code>GoodInfoDTO</code>实例。Controller代码实现如下所示：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br></pre></td><td class="code"><pre><span class="line">package com.yuqiyu.chapter30.controller;</span><br><span class="line"></span><br><span class="line">import com.yuqiyu.chapter30.bean.GoodInfoBean;</span><br><span class="line">import com.yuqiyu.chapter30.bean.GoodTypeBean;</span><br><span class="line">import com.yuqiyu.chapter30.dto.GoodInfoDTO;</span><br><span class="line">import com.yuqiyu.chapter30.jpa.GoodInfoJPA;</span><br><span class="line">import com.yuqiyu.chapter30.jpa.GoodTypeJPA;</span><br><span class="line">import com.yuqiyu.chapter30.mapper.GoodInfoMapper;</span><br><span class="line">import org.springframework.beans.factory.annotation.Autowired;</span><br><span class="line">import org.springframework.web.bind.annotation.PathVariable;</span><br><span class="line">import org.springframework.web.bind.annotation.RequestMapping;</span><br><span class="line">import org.springframework.web.bind.annotation.RestController;</span><br><span class="line"></span><br><span class="line">/**</span><br><span class="line"> * 测试控制器</span><br><span class="line"> * ========================</span><br><span class="line"> * Created with IntelliJ IDEA.</span><br><span class="line"> * User：恒宇少年</span><br><span class="line"> * Date：2017/8/20</span><br><span class="line"> * Time：12:24</span><br><span class="line"> * 码云：http://git.oschina.net/jnyqy</span><br><span class="line"> * ========================</span><br><span class="line"> */</span><br><span class="line">@RestController</span><br><span class="line">public class GoodInfoController</span><br><span class="line">&#123;</span><br><span class="line">    /**</span><br><span class="line">     * 注入商品基本信息jpa</span><br><span class="line">     */</span><br><span class="line">    @Autowired</span><br><span class="line">    private GoodInfoJPA goodInfoJPA;</span><br><span class="line">    /**</span><br><span class="line">     * 注入商品类型jpa</span><br><span class="line">     */</span><br><span class="line">    @Autowired</span><br><span class="line">    private GoodTypeJPA goodTypeJPA;</span><br><span class="line">    /**</span><br><span class="line">     * 注入mapStruct转换Mapper</span><br><span class="line">     */</span><br><span class="line">    @Autowired</span><br><span class="line">    private GoodInfoMapper goodInfoMapper;</span><br><span class="line"></span><br><span class="line">    /**</span><br><span class="line">     * 查询商品详情</span><br><span class="line">     * @param id</span><br><span class="line">     * @return</span><br><span class="line">     */</span><br><span class="line">    @RequestMapping(value = &quot;/detail/&#123;id&#125;&quot;)</span><br><span class="line">    public GoodInfoDTO detail(@PathVariable(&quot;id&quot;) Long id)</span><br><span class="line">    &#123;</span><br><span class="line">        //查询商品基本信息</span><br><span class="line">        GoodInfoBean goodInfoBean = goodInfoJPA.findOne(id);</span><br><span class="line">        //查询商品类型基本信息</span><br><span class="line">        GoodTypeBean typeBean = goodTypeJPA.findOne(goodInfoBean.getTypeId());</span><br><span class="line">        //返回转换dto</span><br><span class="line">        return goodInfoMapper.from(goodInfoBean,typeBean);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>在Controller内我们注入了<code>GoodInfoJPA</code>、<code>GoodTypeJPA</code>以及<code>GoodInfoMapper</code>，在查询商品详情方法时做出了映射处理。接下来我们启动项目访问地址<a href="http://127.0.0.1:8080/detail/1" target="_blank" rel="noopener">http://127.0.0.1:8080/detail/1</a>查看界面输出效果，如下所示：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">goodId: &quot;1&quot;,</span><br><span class="line">goodName: &quot;芹菜&quot;,</span><br><span class="line">goodPrice: 12.4,</span><br><span class="line">typeName: &quot;青菜&quot;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>可以看到界面输出了<code>GoodInfoDTO</code>内的所有字段内容，并且通过from方法将对应配置的<code>target</code>字段赋值。</p>
<h1 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h1><p>本章主要讲述了基于<code>SpringBoot</code>开发框架上集成<code>MapStruct</code>自动映射框架，完成模拟多表获取数据后将某一些字段通过<code>@Mapping</code>配置自动映射到DTO实体实例指定的字段内。<br><code>MapStruct</code>官方文档地址：<a href="http://mapstruct.org/documentation/dev/reference/html/" target="_blank" rel="noopener">http://mapstruct.org/documentation/dev/reference/html/</a></p>
<p>本章代码已经上传到码云：<br>SpringBoot配套源码地址：<a href="https://gitee.com/hengboy/spring-boot-chapter" target="_blank" rel="noopener">https://gitee.com/hengboy/spring-boot-chapter</a><br>SpringCloud配套源码地址：<a href="https://gitee.com/hengboy/spring-cloud-chapter" target="_blank" rel="noopener">https://gitee.com/hengboy/spring-cloud-chapter</a><br>SpringBoot相关系列文章请访问：<a href="http://www.jianshu.com/p/9a08417e4e84" target="_blank" rel="noopener">目录：SpringBoot学习目录</a><br>QueryDSL相关系列文章请访问：<a href="http://www.jianshu.com/p/99a5ec5c3bd5" target="_blank" rel="noopener">QueryDSL通用查询框架学习目录</a><br>SpringDataJPA相关系列文章请访问：<a href="http://www.jianshu.com/p/615ed9c1fe84" target="_blank" rel="noopener">目录：SpringDataJPA学习目录</a><br>感谢阅读！<br>欢迎加入QQ技术交流群，共同进步。<br><img src="http://upload-images.jianshu.io/upload_images/4461954-f1d4cb64234b160a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="">QQ技术交流群</p>

        
        </div>
        <footer class="article-footer">
            <div class="share-container">


    <div class="bdsharebuttonbox">
    <a href="#" class="bds_more" data-cmd="more">分享到：</a>
    <a href="#" class="bds_qzone" data-cmd="qzone" title="分享到QQ空间">QQ空间</a>
    <a href="#" class="bds_tsina" data-cmd="tsina" title="分享到新浪微博">新浪微博</a>
    <a href="#" class="bds_tqq" data-cmd="tqq" title="分享到腾讯微博">腾讯微博</a>
    <a href="#" class="bds_renren" data-cmd="renren" title="分享到人人网">人人网</a>
    <a href="#" class="bds_weixin" data-cmd="weixin" title="分享到微信">微信</a>
</div>
<script>
window._bd_share_config={"common":{"bdSnsKey":{},"bdText":"","bdMini":"2","bdMiniList":false,"bdPic":"","bdStyle":"0","bdSize":"16"},"share":{"bdSize":16}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];
</script>
<style>
    .bdshare_popup_box {
        border-radius: 4px;
        border: #e1e1e1 solid 1px;
    }
    .bdshare-button-style0-16 a,
    .bdshare-button-style0-16 .bds_more {
        padding-left: 20px;
        margin: 6px 10px 6px 0;
    }
    .bdshare_dialog_list a,
    .bdshare_popup_list a,
    .bdshare_popup_bottom a {
        font-family: 'Microsoft Yahei';
    }
    .bdshare_popup_top {
        display: none;
    }
    .bdshare_popup_bottom {
        height: auto;
        padding: 5px;
    }
</style>


</div>

            
    

        </footer>
    </div>
    
        
<nav id="article-nav">
    
        <a href="/spring-boot-chapter-31/" id="article-nav-newer" class="article-nav-link-wrap">
            <strong class="article-nav-caption">上一篇</strong>
            <div class="article-nav-title">
                
                    第三十一章：SpringBoot配置文件application.properties参数详解
                
            </div>
        </a>
    
    
        <a href="/spring-boot-chapter-29/" id="article-nav-older" class="article-nav-link-wrap">
            <strong class="article-nav-caption">下一篇</strong>
            <div class="article-nav-title">第二十九章：基于SpringBoot平台使用Lombok来优雅的编码</div>
        </a>
    
</nav>


    
</article>


    
    

</section>
            
			
				
<aside id="sidebar">
   
        
    <div class="widget-wrap">
        <h3 class="widget-title">最新文章</h3>
        <div class="widget">
            <ul id="recent-post" class="no-thumbnail">
                
                    <li>
                        
                        <div class="item-inner">
                            <p class="item-category"><a class="article-category-link" href="/categories/SpringBoot-核心技术/">SpringBoot 核心技术</a></p>
                            <p class="item-title"><a href="/spring-boot-chapter-52/" class="title">第五十二章：基于SpringBoot2使用Rest访问MongoDB数据</a></p>
                            <p class="item-date"><time datetime="2018-04-21T16:00:00.000Z" itemprop="datePublished">2018-04-22</time></p>
                        </div>
                    </li>
                
                    <li>
                        
                        <div class="item-inner">
                            <p class="item-category"><a class="article-category-link" href="/categories/SpringBoot-核心技术/">SpringBoot 核心技术</a></p>
                            <p class="item-title"><a href="/spring-boot-chapter-51/" class="title">第五十一章：基于SpringBoot2 &amp; MongoDB完成自动化集成</a></p>
                            <p class="item-date"><time datetime="2018-04-15T16:00:00.000Z" itemprop="datePublished">2018-04-16</time></p>
                        </div>
                    </li>
                
                    <li>
                        
                        <div class="item-inner">
                            <p class="item-category"><a class="article-category-link" href="/categories/SpringBoot-核心技术/">SpringBoot 核心技术</a></p>
                            <p class="item-title"><a href="/spring-boot-chapter-50/" class="title">第五十章：SpringBoot2.0新特性 - 岂止至今最简单redis缓存集成</a></p>
                            <p class="item-date"><time datetime="2018-04-14T16:00:00.000Z" itemprop="datePublished">2018-04-15</time></p>
                        </div>
                    </li>
                
                    <li>
                        
                        <div class="item-inner">
                            <p class="item-category"><a class="article-category-link" href="/categories/SpringBoot-核心技术/">SpringBoot 核心技术</a></p>
                            <p class="item-title"><a href="/spring-boot-chapter-49/" class="title">第四十九章：SpringBoot2.0新特性 - 你get到WebMvcConfigurer两种配置方式了吗？</a></p>
                            <p class="item-date"><time datetime="2018-03-16T16:00:00.000Z" itemprop="datePublished">2018-03-17</time></p>
                        </div>
                    </li>
                
                    <li>
                        
                        <div class="item-inner">
                            <p class="item-category"><a class="article-category-link" href="/categories/SpringBoot-核心技术/">SpringBoot 核心技术</a></p>
                            <p class="item-title"><a href="/spring-boot-chapter-48/" class="title">第四十八章：SpringBoot2.0新特性 - RabbitMQ信任package设置</a></p>
                            <p class="item-date"><time datetime="2018-03-12T16:00:00.000Z" itemprop="datePublished">2018-03-13</time></p>
                        </div>
                    </li>
                
            </ul>
        </div>
    </div>

    
        
    <div class="widget-wrap">
        <h3 class="widget-title">分类</h3>
        <div class="widget">
            <ul class="category-list"><li class="category-list-item"><a class="category-list-link" href="/categories/QueryDSL-核心技术/">QueryDSL 核心技术</a><span class="category-list-count">7</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/SpringBoot-核心技术/">SpringBoot 核心技术</a><span class="category-list-count">36</span></li></ul>
        </div>
    </div>

    
        
    <div class="widget-wrap">
        <h3 class="widget-title">归档</h3>
        <div class="widget">
            <ul class="archive-list"><li class="archive-list-item"><a class="archive-list-link" href="/archives/2018/04/">四月 2018</a><span class="archive-list-count">3</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2018/03/">三月 2018</a><span class="archive-list-count">4</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2018/01/">一月 2018</a><span class="archive-list-count">1</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2017/12/">十二月 2017</a><span class="archive-list-count">4</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2017/11/">十一月 2017</a><span class="archive-list-count">2</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2017/10/">十月 2017</a><span class="archive-list-count">2</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2017/09/">九月 2017</a><span class="archive-list-count">4</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2017/08/">八月 2017</a><span class="archive-list-count">4</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2017/07/">七月 2017</a><span class="archive-list-count">9</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2017/06/">六月 2017</a><span class="archive-list-count">2</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2017/05/">五月 2017</a><span class="archive-list-count">3</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2017/04/">四月 2017</a><span class="archive-list-count">5</span></li></ul>
        </div>
    </div>

    
        
    <div class="widget-wrap">
        <h3 class="widget-title">标签</h3>
        <div class="widget">
            <ul class="tag-list"><li class="tag-list-item"><a class="tag-list-link" href="/tags/QueryDSL/">QueryDSL</a><span class="tag-list-count">7</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/SpringBoot/">SpringBoot</a><span class="tag-list-count">43</span></li></ul>
        </div>
    </div>

    
        
    <div class="widget-wrap">
        <h3 class="widget-title">标签云</h3>
        <div class="widget tagcloud">
            <a href="/tags/QueryDSL/" style="font-size: 10px;">QueryDSL</a> <a href="/tags/SpringBoot/" style="font-size: 20px;">SpringBoot</a>
        </div>
    </div>

    
        
    <div class="widget-wrap widget-list">
        <h3 class="widget-title">链接</h3>
        <div class="widget">
            <ul>
                
                    <li>
     				<a href="http://hexo.io" target="_blank">Hexo</a>
					</li>
                
            </ul>
        </div>
    </div>


    
    <div id="toTop" class="fa fa-angle-up"></div>
</aside>

				
        </div>
        <!--引入不蒜子-->
<script async src="//dn-lbstatics.qbox.me/busuanzi/2.3/busuanzi.pure.mini.js"></script>
<footer id="footer">
    <div class="outer">
        <div id="footer-info" class="inner">
            <span  id="busuanzi_container_site_pv">本站总访问量<span id="busuanzi_value_site_pv"></span>次</span>
            &copy; 2017 - 2018 恒宇少年 - 版权所有<br>
        </div>
    </div>
</footer>

        


    
        <script src="/libs/lightgallery/js/lightgallery.min.js"></script>
        <script src="/libs/lightgallery/js/lg-thumbnail.min.js"></script>
        <script src="/libs/lightgallery/js/lg-pager.min.js"></script>
        <script src="/libs/lightgallery/js/lg-autoplay.min.js"></script>
        <script src="/libs/lightgallery/js/lg-fullscreen.min.js"></script>
        <script src="/libs/lightgallery/js/lg-zoom.min.js"></script>
        <script src="/libs/lightgallery/js/lg-hash.min.js"></script>
        <script src="/libs/lightgallery/js/lg-share.min.js"></script>
        <script src="/libs/lightgallery/js/lg-video.min.js"></script>
    
    
        <script src="/libs/justified-gallery/jquery.justifiedGallery.min.js"></script>
    
    



<!-- Custom Scripts -->
<script src="/js/main.js"></script>

    </div>
</body>
</html>